/*******************************************************************************
  * 文件：UartComm_Message.c
  * 作者：zyz
  * 版本：v1.0.0
  * 日期：2017-08-03
  * 说明：消息
*******************************************************************************/

/* 头文件 *********************************************************************/
#include "UartComm_Message.h"
#include "UartComm_Driver.h"
#include "UartComm.h"
#include "main.h"
#include "Fota.h"
#include "JumpFunction.h"
#include "Heartbeat.h"


/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/
/*******************************************************************************
  * 函数名: UartComm_InitMessage
  * 功  能：初始化消息
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void UartComm_InitMessage(void)
{
}

/*******************************************************************************
  * 函数名：UartComm_RecvReqInquireSwVerMsg
  * 功  能：接收请求查询软件版本消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0x01
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvReqInquireSwVerMsg)
{
    U8* pu8Data;
    U16ToU8_tu uYear;

    // 构建发送数据包
    pu8Data = UartComm_SetupSendPacket(psPacket->u8SeqNum,
        psPacket->u8SrcAddr, u8UARTCOMM_CMD_RES_INQUIRE_SW_VER);
    // 版本
    *pu8Data++ = u8SW_MAJOR_VERSION;             // 主版本
    *pu8Data++ = u8SW_MINOR_VERSION;             // 次版本
    *pu8Data++ = u8SW_REVISION_VERSION;          // 修订版本
    uYear.u16Word = u16SW_EXTENDED_VERSION_YEAR;
    *pu8Data++ = uYear.sByte.u8Msb;              // 延伸版本，年MSB
    *pu8Data++ = uYear.sByte.u8Lsb;              // 延伸版本，年LSB
    *pu8Data++ = u8SW_EXTENDED_VERSION_MONTH;    // 延伸版本，月
    *pu8Data++ = u8SW_EXTENDED_VERSION_DAY;      // 延伸版本，日
    // 发送响应读数据包
    UartComm_SendPacket(ePort, pu8Data);
}

/*******************************************************************************
  * 函数名：UartComm_RecvReqInquireSwIdMsg
  * 功  能：接收请求查询软件标识符消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0x03
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvReqInquireSwIdMsg)
{
    U8* pu8Data;
    U8 u8Len;

    // 构建发送数据包
    pu8Data = UartComm_SetupSendPacket(psPacket->u8SeqNum,
        psPacket->u8SrcAddr, u8UARTCOMM_CMD_RES_INQUIRE_SW_ID);
    // 软件标识符
    u8Len = (U8)strlen(strSW_ID);
    memcpy(pu8Data, strSW_ID, u8Len);
    pu8Data += u8Len;
    // 发送响应读数据包
    UartComm_SendPacket(ePort, pu8Data);
}

/*******************************************************************************
  * 函数名：UartComm_RecvReqHeartbeatMsg
  * 功  能：接收请求心跳消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0x11
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvReqHeartbeatMsg)
{
    U8 *pu8Data;

    // 构建发送数据包
    pu8Data = UartComm_SetupSendPacket(psPacket->u8SeqNum,
        psPacket->u8SrcAddr, u8UARTCOMM_CMD_RES_HEARTBEAT);
    // 发送响应读数据包
    UartComm_SendPacket(ePort, pu8Data);
}

/*******************************************************************************
  * 函数名：UartComm_RecvOtaReqNotifyUpgradeMsg
  * 功  能：接收OTA请求通知升级消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0xA1
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvOtaReqNotifyUpgradeMsg)
{
    U8 *pu8Data;
    U32ToU8_tu uOffset;

    // 激活心跳
    Heartbeat_Active();

    // 发送响应数据包，接受升级
    pu8Data = UartComm_SetupSendPacket(psPacket->u8SeqNum,
        psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_RES_NOTIFY_UPGRADE);
    *pu8Data++ = 0x01;
    UartComm_SendPacket(ePort, pu8Data);

    // 设置校验信息状态
    Fota_SetState(eFOTA_STATE_VERIFY_INFO);

    // 开始获取校验信息
    pu8Data = UartComm_SetupSendPacket(0,
        psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_GET_FIRMWARE);
    uOffset.u32Word = u32APPLICATION_HEADER_ADDRESS - u32APPLICATION_ADDRESS;
    *pu8Data++ = uOffset.sByte.u8HighMsb;
    *pu8Data++ = uOffset.sByte.u8HighLsb;
    *pu8Data++ = uOffset.sByte.u8LowMsb;
    *pu8Data++ = uOffset.sByte.u8LowLsb;
    *pu8Data++ = sizeof(ImageHeader_ts);
    UartComm_SendPacket(ePort, pu8Data);
}

/*******************************************************************************
  * 函数名：UartComm_RecvOtaResGetFirmwareMsg
  * 功  能：接收OTA响应获取固件消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0xA4
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvOtaResGetFirmwareMsg)
{
    U8 *pu8Data;
    U32 u32Offset;
    U8 u8Len;
    Bool bResult;
    FotaState_te eState;
    U32ToU8_tu uOffset;
    U8 *pu8MsgData = psPacket->uData.sComMsgData.au8Data;

    // 激活心跳
    Heartbeat_Active();

    // 获取状态
    eState = Fota_GetState();

    // 校验信息状态
    if(eState == eFOTA_STATE_VERIFY_INFO)
    {
        // 校验信息
        ImageHeader_ts *psHeader = (ImageHeader_ts *)&pu8MsgData[5];
        FotaVerifyResult_te eResult = Fota_VerifyImageInfo(psHeader);

        // 接受升级
        if(eResult == eFOTA_VERIFY_RESULT_ACCEPT)
        {
            // 准备升级
            Fota_PrepareUpdate(psHeader->u32ImageAddress, psHeader->u32ImageSize);
            // 设置写入状态
            Fota_SetState(eFOTA_STATE_WRITE_IMAGE);
            // 获取程序数据参数
            bResult = Fota_GetImageDataPara(&u32Offset, &u8Len);
            if((bResult == FALSE) && (u8Len > 0))
            {
                // 开始获取固件
                pu8Data = UartComm_SetupSendPacket(0,
                    psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_GET_FIRMWARE);
                uOffset.u32Word = u32Offset;
                *pu8Data++ = uOffset.sByte.u8HighMsb;
                *pu8Data++ = uOffset.sByte.u8HighLsb;
                *pu8Data++ = uOffset.sByte.u8LowMsb;
                *pu8Data++ = uOffset.sByte.u8LowLsb;
                *pu8Data++ = u8Len;
                UartComm_SendPacket(ePort, pu8Data);
            }
            else
            {
                // 重置为准备状态
                Fota_SetState(eFOTA_STATE_READY);
            }
        }
        // 拒绝升级
        else if(eResult == eFOTA_VERIFY_RESULT_REFUSE)
        {
            // 设置完成状态
            Fota_SetState(eFOTA_STATE_COMPLETED);

            // 上报升级结果，升级失败
            pu8Data = UartComm_SetupSendPacket(0,
                psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_FEEDBACK_RESULT);
            *pu8Data++ = 0x01;
            UartComm_SendPacket(ePort, pu8Data);
        }
        // 不需要升级
        else if(eResult == eFOTA_VERIFY_RESULT_NONEED)
        {
            // 设置完成状态
            Fota_SetState(eFOTA_STATE_COMPLETED);

            // 上报升级结果，升级成功
            pu8Data = UartComm_SetupSendPacket(0,
                psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_FEEDBACK_RESULT);
            *pu8Data++ = 0x00;
            UartComm_SendPacket(ePort, pu8Data);
        }
    }
    // 写入程序状态
    else if(eState == eFOTA_STATE_WRITE_IMAGE)
    {
        // 获取偏移，更新程序数据
        uOffset.sByte.u8HighMsb = pu8MsgData[0];
        uOffset.sByte.u8HighLsb = pu8MsgData[1];
        uOffset.sByte.u8LowMsb  = pu8MsgData[2];
        uOffset.sByte.u8LowLsb  = pu8MsgData[3];
        Fota_UpdateImageData(uOffset.u32Word, &pu8MsgData[5], pu8MsgData[4]);

        // 获取程序数据参数
        bResult = Fota_GetImageDataPara(&u32Offset, &u8Len);
        // 未升级完成
        if(bResult == FALSE)
        {
            // 继续获取固件
            if(u8Len > 0)
            {
                // 开始获取固件
                pu8Data = UartComm_SetupSendPacket(0,
                    psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_GET_FIRMWARE);
                uOffset.u32Word = u32Offset;
                *pu8Data++ = uOffset.sByte.u8HighMsb;
                *pu8Data++ = uOffset.sByte.u8HighLsb;
                *pu8Data++ = uOffset.sByte.u8LowMsb;
                *pu8Data++ = uOffset.sByte.u8LowLsb;
                *pu8Data++ = u8Len;
                UartComm_SendPacket(ePort, pu8Data);
            }
            else
            {
                // 重置为准备状态
                Fota_SetState(eFOTA_STATE_READY);
            }
        }
        // 升级完成
        else
        {
            // 设置完成状态
            Fota_SetState(eFOTA_STATE_COMPLETED);

            // 上报升级结果
            pu8Data = UartComm_SetupSendPacket(0,
                psPacket->u8SrcAddr, u8UARTCOMM_CMD_OTA_REQ_FEEDBACK_RESULT);
            // 校验程序
            if(VerifyImage(eIMAGE_TYPE_APPLICATION) == TRUE)
            {
                *pu8Data++ = 0x00;    // 升级成功
            }
            else
            {
                *pu8Data++ = 0x01;    // 升级失败
            }
            UartComm_SendPacket(ePort, pu8Data);
        }
    }
}

/*******************************************************************************
  * 函数名：UartComm_RecvOtaResFeedbackResultMsg
  * 功  能：接收OTA响应反馈结果消息
  * 参  数：ePort    - 端口
  *         psPacket - 接收数据包指针
  * 返回值：无
  * 说  明：接收 命令0xA6
*******************************************************************************/
UARTCOMM_MSG_HANDLER(UartComm_RecvOtaResFeedbackResultMsg)
{
    // 完成升级状态
    // 则跳转到应用程序
    if(Fota_GetState() == eFOTA_STATE_COMPLETED)
    {
        JumpToApplication();
    }
}

/***************************** 文件结束 ***************************************/
